﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathematicallySafe.HeadCounter.Data;
using MathematicallySafe.HeadCounter.Data.Common;
using MathematicallySafe.HeadCounter.Data.Interfaces;
using MathematicallySafe.HeadCounter.Data.Models;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Services.Calculators
{
    class StandardDeviationCalculator: Processor<Raider>
    {
        private readonly IGuild Guild = ObjectFactory.GetInstance<IGuild>();

        private double _lootRateAverage;
        private double _weightedLootRateAverage;

        protected override void Initialise()
        {
            _lootRateAverage = Guild.ActiveRaiders.Where(r => r.LifetimeAttendance >= 0.5).Average(r => r.LifetimeLootRate);
            _weightedLootRateAverage = Guild.ActiveRaiders.Where(r => r.LifetimeAttendance >= 0.5).Average(r => r.LifetimeWeightedLootRate);

            Guild.LootRateStdDev = CalculateStandardDeviation(Guild.ActiveRaiders.Where(r => r.LifetimeAttendance >= 0.5).Select(r => r.LifetimeLootRate));
            Guild.WeightedLootRateStdDev = CalculateStandardDeviation(Guild.ActiveRaiders.Where(r => r.LifetimeAttendance >= 0.5).Select(r => r.LifetimeWeightedLootRate));
        }

        private double CalculateStandardDeviation(IEnumerable<double> values)
        {
            var mean = values.Average();
            var squareOfDeviations = (values.Select(v => Math.Pow((v - mean), 2))).Sum();
            return Math.Sqrt(squareOfDeviations / (values.Count() - 1));
        }

        protected override void Process(Raider item)
        {
            item.StdDevsFromLootRateMean = (item.LifetimeLootRate - _lootRateAverage) / Guild.LootRateStdDev;
            item.StdDevsFromWeightedLootRateMean = (item.LifetimeWeightedLootRate - _weightedLootRateAverage) / Guild.LootRateStdDev;
        }
    }
}
